<?php

namespace WebmanGrpc;

use WebmanGrpc\Initializer\Initializer;
use WebmanGrpc\Pool\ConnectionPool;
use WebmanGrpc\Serialization\SerializationOptimizer;
use WebmanGrpc\Memory\MemoryManager;
use WebmanGrpc\Module\ModuleManager;
use WebmanGrpc\Event\EventBus;
use WebmanGrpc\Event\LifecycleEventManager;

/**
 * 性能监控器
 * 
 * 提供gRPC扩展包的性能监控和统计功能
 */
class PerformanceMonitor
{
    /**
     * 单例实例
     * @var PerformanceMonitor|null
     */
    protected static ?PerformanceMonitor $instance = null;
    
    /**
     * 性能数据
     * @var array
     */
    protected array $performanceData = [
        'requests' => [
            'total' => 0,
            'success' => 0,
            'failed' => 0,
            'duration' => [
                'total' => 0,
                'min' => PHP_FLOAT_MAX,
                'max' => 0,
                'avg' => 0,
            ],
            'size' => [
                'total_request' => 0,
                'total_response' => 0,
                'avg_request' => 0,
                'avg_response' => 0,
            ],
        ],
        'connections' => [],
        'serialization' => [],
        'memory' => [],
        'modules' => [],
        'events' => [],
    ];
    
    /**
     * 是否启用监控
     * @var bool
     */
    protected bool $enabled = true;
    
    /**
     * 最大历史记录数
     * @var int
     */
    protected int $maxHistorySize = 1000;
    
    /**
     * 请求历史记录
     * @var array
     */
    protected array $requestHistory = [];
    
    /**
     * 构造函数
     */
    protected function __construct()
    {
        // 注册生命周期钩子
        $lifecycleEventManager = LifecycleEventManager::getInstance();
        $lifecycleEventManager->addHook('shutdown', [$this, 'savePerformanceData'], 0);
    }
    
    /**
     * 获取单例实例
     * 
     * @return PerformanceMonitor
     */
    public static function getInstance(): PerformanceMonitor
    {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        
        return self::$instance;
    }
    
    /**
     * 记录请求开始
     * 
     * @param string $method 方法名
     * @param string $service 服务名
     * @param array $metadata 元数据
     * @return string 请求ID
     */
    public function startRequest(string $method, string $service, array $metadata = []): string
    {
        if (!$this->enabled) {
            return '';
        }
        
        $requestId = uniqid('grpc_', true);
        $startTime = microtime(true);
        
        $this->requestHistory[$requestId] = [
            'method' => $method,
            'service' => $service,
            'metadata' => $metadata,
            'start_time' => $startTime,
            'end_time' => null,
            'duration' => null,
            'success' => null,
            'request_size' => 0,
            'response_size' => 0,
            'error' => null,
        ];
        
        return $requestId;
    }
    
    /**
     * 记录请求结束
     * 
     * @param string $requestId 请求ID
     * @param bool $success 是否成功
     * @param int $requestSize 请求大小
     * @param int $responseSize 响应大小
     * @param string|null $error 错误信息
     * @return void
     */
    public function endRequest(string $requestId, bool $success, int $requestSize = 0, int $responseSize = 0, ?string $error = null): void
    {
        if (!$this->enabled || !isset($this->requestHistory[$requestId])) {
            return;
        }
        
        $endTime = microtime(true);
        $duration = $endTime - $this->requestHistory[$requestId]['start_time'];
        
        $this->requestHistory[$requestId]['end_time'] = $endTime;
        $this->requestHistory[$requestId]['duration'] = $duration;
        $this->requestHistory[$requestId]['success'] = $success;
        $this->requestHistory[$requestId]['request_size'] = $requestSize;
        $this->requestHistory[$requestId]['response_size'] = $responseSize;
        $this->requestHistory[$requestId]['error'] = $error;
        
        // 更新性能数据
        $this->updatePerformanceData($this->requestHistory[$requestId]);
        
        // 清理历史记录
        $this->cleanupHistory();
    }
    
    /**
     * 更新性能数据
     * 
     * @param array $requestData 请求数据
     * @return void
     */
    protected function updatePerformanceData(array $requestData): void
    {
        // 更新请求计数
        $this->performanceData['requests']['total']++;
        
        if ($requestData['success']) {
            $this->performanceData['requests']['success']++;
        } else {
            $this->performanceData['requests']['failed']++;
        }
        
        // 更新持续时间统计
        $duration = $requestData['duration'];
        $this->performanceData['requests']['duration']['total'] += $duration;
        $this->performanceData['requests']['duration']['min'] = min($this->performanceData['requests']['duration']['min'], $duration);
        $this->performanceData['requests']['duration']['max'] = max($this->performanceData['requests']['duration']['max'], $duration);
        $this->performanceData['requests']['duration']['avg'] = $this->performanceData['requests']['duration']['total'] / $this->performanceData['requests']['total'];
        
        // 更新大小统计
        $requestSize = $requestData['request_size'];
        $responseSize = $requestData['response_size'];
        $this->performanceData['requests']['size']['total_request'] += $requestSize;
        $this->performanceData['requests']['size']['total_response'] += $responseSize;
        $this->performanceData['requests']['size']['avg_request'] = $this->performanceData['requests']['size']['total_request'] / $this->performanceData['requests']['total'];
        $this->performanceData['requests']['size']['avg_response'] = $this->performanceData['requests']['size']['total_response'] / $this->performanceData['requests']['total'];
    }
    
    /**
     * 清理历史记录
     * 
     * @return void
     */
    protected function cleanupHistory(): void
    {
        if (count($this->requestHistory) > $this->maxHistorySize) {
            $this->requestHistory = array_slice($this->requestHistory, -$this->maxHistorySize, null, true);
        }
    }
    
    /**
     * 获取性能数据
     * 
     * @return array 性能数据
     */
    public function getPerformanceData(): array
    {
        // 更新组件数据
        $this->updateComponentData();
        
        return $this->performanceData;
    }
    
    /**
     * 更新组件数据
     * 
     * @return void
     */
    protected function updateComponentData(): void
    {
        // 连接池数据
        $connectionPool = ConnectionPool::getInstance();
        $this->performanceData['connections'] = $connectionPool->getStats();
        
        // 序列化数据
        $this->performanceData['serialization'] = SerializationOptimizer::getStats();
        
        // 内存数据
        $this->performanceData['memory'] = MemoryManager::getMemoryStats();
        
        // 模块数据
        $this->performanceData['modules'] = ModuleManager::getAllModuleStatus();
        
        // 事件数据
        $eventBus = EventBus::getInstance();
        $this->performanceData['events'] = $eventBus->getStats();
    }
    
    /**
     * 获取请求历史
     * 
     * @param int $limit 限制数量
     * @param bool $onlyFailed 仅获取失败的请求
     * @return array 请求历史
     */
    public function getRequestHistory(int $limit = 100, bool $onlyFailed = false): array
    {
        $history = $this->requestHistory;
        
        if ($onlyFailed) {
            $history = array_filter($history, function ($request) {
                return !$request['success'];
            });
        }
        
        // 按时间倒序排序
        uasort($history, function ($a, $b) {
            return $b['start_time'] <=> $a['start_time'];
        });
        
        return array_slice($history, 0, $limit);
    }
    
    /**
     * 启用监控
     * 
     * @return void
     */
    public function enable(): void
    {
        $this->enabled = true;
    }
    
    /**
     * 禁用监控
     * 
     * @return void
     */
    public function disable(): void
    {
        $this->enabled = false;
    }
    
    /**
     * 检查是否启用监控
     * 
     * @return bool 是否启用监控
     */
    public function isEnabled(): bool
    {
        return $this->enabled;
    }
    
    /**
     * 设置最大历史记录数
     * 
     * @param int $maxHistorySize 最大历史记录数
     * @return void
     */
    public function setMaxHistorySize(int $maxHistorySize): void
    {
        $this->maxHistorySize = $maxHistorySize;
        $this->cleanupHistory();
    }
    
    /**
     * 重置性能数据
     * 
     * @return void
     */
    public function reset(): void
    {
        $this->performanceData = [
            'requests' => [
                'total' => 0,
                'success' => 0,
                'failed' => 0,
                'duration' => [
                    'total' => 0,
                    'min' => PHP_FLOAT_MAX,
                    'max' => 0,
                    'avg' => 0,
                ],
                'size' => [
                    'total_request' => 0,
                    'total_response' => 0,
                    'avg_request' => 0,
                    'avg_response' => 0,
                ],
            ],
            'connections' => [],
            'serialization' => [],
            'memory' => [],
            'modules' => [],
            'events' => [],
        ];
        
        $this->requestHistory = [];
    }
    
    /**
     * 保存性能数据
     * 
     * @return void
     */
    public function savePerformanceData(): void
    {
        // 这里可以实现将性能数据保存到文件或数据库
        // 例如：
        // file_put_contents('/path/to/performance_data.json', json_encode($this->getPerformanceData()));
    }
    
    /**
     * 生成性能报告
     * 
     * @return string 性能报告
     */
    public function generateReport(): string
    {
        $data = $this->getPerformanceData();
        
        $report = "=== gRPC Performance Report ===\n\n";
        
        // 请求统计
        $report .= "Request Statistics:\n";
        $report .= "  Total: {$data['requests']['total']}\n";
        $report .= "  Success: {$data['requests']['success']}\n";
        $report .= "  Failed: {$data['requests']['failed']}\n";
        $report .= "  Success Rate: " . ($data['requests']['total'] > 0 ? round($data['requests']['success'] / $data['requests']['total'] * 100, 2) : 0) . "%\n";
        $report .= "  Average Duration: " . round($data['requests']['duration']['avg'] * 1000, 2) . "ms\n";
        $report .= "  Min Duration: " . round($data['requests']['duration']['min'] * 1000, 2) . "ms\n";
        $report .= "  Max Duration: " . round($data['requests']['duration']['max'] * 1000, 2) . "ms\n";
        $report .= "  Average Request Size: " . round($data['requests']['size']['avg_request'] / 1024, 2) . "KB\n";
        $report .= "  Average Response Size: " . round($data['requests']['size']['avg_response'] / 1024, 2) . "KB\n\n";
        
        // 连接池统计
        if (!empty($data['connections'])) {
            $report .= "Connection Pool Statistics:\n";
            $report .= "  Active Connections: {$data['connections']['active_connections']}\n";
            $report .= "  Total Connections: {$data['connections']['total_connections']}\n";
            $report .= "  Connection Hits: {$data['connections']['hits']}\n";
            $report .= "  Connection Misses: {$data['connections']['misses']}\n";
            $report .= "  Hit Rate: " . ($data['connections']['hits'] + $data['connections']['misses'] > 0 ? round($data['connections']['hits'] / ($data['connections']['hits'] + $data['connections']['misses']) * 100, 2) : 0) . "%\n\n";
        }
        
        // 序列化统计
        if (!empty($data['serialization'])) {
            $report .= "Serialization Statistics:\n";
            $report .= "  Pool Hits: {$data['serialization']['pool_hits']}\n";
            $report .= "  Pool Misses: {$data['serialization']['pool_misses']}\n";
            $report .= "  Cache Hits: {$data['serialization']['cache_hits']}\n";
            $report .= "  Cache Misses: {$data['serialization']['cache_misses']}\n";
            $report .= "  Pool Hit Rate: " . ($data['serialization']['pool_hits'] + $data['serialization']['pool_misses'] > 0 ? round($data['serialization']['pool_hits'] / ($data['serialization']['pool_hits'] + $data['serialization']['pool_misses']) * 100, 2) : 0) . "%\n";
            $report .= "  Cache Hit Rate: " . ($data['serialization']['cache_hits'] + $data['serialization']['cache_misses'] > 0 ? round($data['serialization']['cache_hits'] / ($data['serialization']['cache_hits'] + $data['serialization']['cache_misses']) * 100, 2) : 0) . "%\n\n";
        }
        
        // 内存统计
        if (!empty($data['memory'])) {
            $report .= "Memory Statistics:\n";
            $report .= "  Current Usage: " . round($data['memory']['current'] / 1024 / 1024, 2) . "MB\n";
            $report .= "  Peak Usage: " . round($data['memory']['peak'] / 1024 / 1024, 2) . "MB\n";
            if (isset($data['memory']['limit'])) {
                $report .= "  Limit: " . round($data['memory']['limit'] / 1024 / 1024, 2) . "MB\n";
                $report .= "  Usage Percentage: " . round($data['memory']['current'] / $data['memory']['limit'] * 100, 2) . "%\n";
            }
            $report .= "\n";
        }
        
        // 模块统计
        if (!empty($data['modules'])) {
            $report .= "Module Statistics:\n";
            foreach ($data['modules'] as $name => $module) {
                $report .= "  {$name}: {$module['status']}\n";
            }
            $report .= "\n";
        }
        
        // 事件统计
        if (!empty($data['events'])) {
            $report .= "Event Statistics:\n";
            $report .= "  Total Events: {$data['events']['total_events']}\n";
            $report .= "  Listeners: {$data['events']['total_listeners']}\n";
            $report .= "\n";
        }
        
        return $report;
    }
}